<?php
/**
 *	Architect Framework
 *
 *	Architect Framework is a light weight object oriented web applications framework written for PHP 5.1.4 and later that provide the tools to develop and deploy a website or application fast and with as little code as possible.
 *
 *	@author Robin Grass, <hello@coffinboy.se>
 *	@link http://architect.kodlabbet.net
 *	@license http://www.opensource.org/licenses/gpl-3.0.html GNU General Public License (v. 3)
 */

/**
 *	Architect_HookAPI
 *
 *	This class does the magic behind the Hooks API.
 *
 *	@package Core
 *	@version 1.0
 *	@author Robin Grass, <hello@coffinboy.se>
 */
class Architect_HookAPI {

	/**
	 *	@staticvar resource $__instance
	 */
	private static $__instance;
	
	/**
	 *	@var array $hooks
	 */
	protected $hooks = array();
	
	/**
	 *	@var array $triggers
	 */
	protected $triggers = array();
	
	/**
	 *	__construct
	 */
	protected function __construct() {}

	/**
	 *	__clone
	 */
	final private function __clone() {}
	
	/**
	 *	getInstance
	 *
	 *	This is method is the most important part of a singleton pattern, it returns the current instance of this class (if any). If the class has not been instanced this method creates a new instance and returns it.
	 *
	 *	@return self::$__instance
	 */
	static public function getInstance() {
		if(!self::$__instance)
			self::$__instance = new self();
	return self::$__instance;
	}
	
	/**
	 *	hasTrigger
	 *
	 *	This method checks if a trigger exists.
	 *
	 *	@param string $id
	 *
	 *	@return bool
	 */
	public function hasTrigger($id) {
		if(array_key_exists($id, $this->triggers))
			return true;
	return false;
	}
	
	/**
	 *	setTrigger
	 *
	 *	This method adds a new trigger.
	 *
	 *	@param string $id
	 */
	public function setTrigger($id) {
		if(!$this->hasTrigger($id))
			$this->triggers[$id] = array();
	}
	
	/**
	 *	getTrigger
	 *
	 *	This method returns a trigger, if any, returns null if not.
	 *
	 *	@pram string $id
	 *
	 *	@return mixed
	 */
	public function getTrigger($id) {
		if($this->hasTrigger($id))
			return $this->triggers[$id];
	return null;
	}
	
	/**
	 *	hasHook
	 *
	 *	This method checks if a hook exists.
	 *
	 *	@param string $id
	 *
	 *	@return bool
	 */
	public function hasHook($id) {
		if(array_key_exists($id, $this->hooks))
			return true;
	return false;
	}
	
	/**
	 *	addHook
	 *
	 *	This method adds a new hook.
	 *
	 *	@param object $hook
	 */
	public function addHook(Architect_Hook $hook) {
		$id = strtolower(get_class($hook));
		$this->setHook($id, $hook);
	}
	
	/**
	 *	setHook
	 *
	 *	This method does pretty much the same as the above, but does not automatically generate a id for the hook.
	 *
	 *	@param string $id
	 *	@param object $hook
	 */
	public function setHook($id, Architect_Hook $hook) {
		$this->hooks[$id] = $hook;
		$hook->register();
	}
	
	/**
	 *	getHook
	 *
	 *	This method returns a hook, if any, returns null if not.
	 *
	 *	@param string $id
	 *
	 *	@return mixed
	 */
	public function getHook($id) {
		if($this->hasHook($id))
			return $this->hooks[$id];
	return null;
	}
	
	/**
	 *	registerHook
	 *
	 *	This method register a hook that has been added to the API and assigns it to a trigger.
	 *
	 *	@param string $hook_id
	 *	@param string $trigger
	 */
	public function registerHook($hook_id, $trigger) {
		if($this->hasHook($hook_id) && $this->hasTrigger($trigger)) {
			array_push($this->triggers[$trigger], $this->getHook($hook_id));
		}
	}
	
	/**
	 *	invokeHook
	 *
	 *	This method invokes a hook.
	 *
	 *	@param string $hook_id
	 */
	public function invokeHook($hook_id) {
		if($this->hasHook($hook_id))
			$this->getHook($hook_id)->invoke();
	}
	
	/**
	 *	invokeHooksByTrigger
	 *
	 *	This method invokes all hooks assigned to a trigger.
	 *
	 *	@param string $trigger
	 */
	public function invokeHooksByTrigger($trigger) {
		if($this->hasTrigger($trigger)) {
			foreach($this->getTrigger($trigger) as $hook)
				$hook->invoke();
		}
	}

}
?>